/**
 * PlacesView.js defines the view object of the applications main view
 * 
 * Places view lists available places nearby
 * Note! We are using this same view also when user has selected
 * some category; when category is selected, the category name is
 * displayed instead of default text 'Nearby places'. Also
 * back button behaviour is different (back goes to categories)
 * 
 */
qype.views.PlacesView = Class.create(View, {
    initialize: function($super, id) {
        $super(id);
        this.currentCategoryName = undefined;

		/* ***************************
		   PLACE OF CODE SNIPPET 10.1
		  ****************************/
		 
        // Create new snippet for the link leading to CategoriesView and bind
        // it to a DOM node.
        var categoriesLink = new Snippet("categoriesLink");

		/* ***************************
		   PLACE OF CODE SNIPPET 10.2
		  ****************************/
		 
        // Add default template
        categoriesLink.onDefault.template.push(qype.str.places_link_to_categories + " >>");

		/* ***************************
		   PLACE OF CODE SNIPPET 10.3
		  ****************************/

        // Event handlers can be attached directly to the DOM node
        var goToCategories = function() {
            this.engine.activateView("categoriesView");
        }
        categoriesLink.dom.addEventListener("click", goToCategories.bind(this), false);

        // Create new snippet for the header and bind to a DOM node.
        var header = new Snippet("placesHeader");

        // Add default template
        header.onDefault.template.push({
            fn: function() { // Gives the appropriate header string for the view
                return this.currentCategoryName || qype.str.places_header_nearby
            },
            base: this
        });

		/* ***************************
		   PLACE OF CODE SNIPPET 11.1
		  ****************************/

        // Create new snippet for the actual content and bind to a DOM node.
        var content = new Snippet("placesContent");

        // Add default template
        content.onDefault.template.push("<div class='progress'></div>");

        // Different rendering when there's required data available
        content.onData.template.push({
            fn: this.constructPlacesHtml,
            base: this
        });

        // When to actually use the onData templates?
        content.onData.doUse = function() {
            return content.data.places !== undefined;
        };

        // And finally register all the Snippets to this view
        this.registerSnippets({
            categoriesLink: categoriesLink,
            header: header
			/* ***************************
			   PLACE OF CODE SNIPPET 11.2
			  ****************************/				
			,
            content: content
        });

        // Register global subscribes 
        this.registerSubscribes([
	        {
	            eventName: "placeClicked",
	            callback: this.onItemClick,			
				context: this
	        },
			{
                eventName: "mapLinkClicked",
                callback: this.onMapLinkClick,
                context: this
            },
			{
                eventName: "locationButtonClicked",
                callback: this.onLocationButtonClick,
                context: this
            }
			
        ]);
    },

    // Templates help separating the JS values and actual HTML content. The templates
    // of Prototype.js are used, even though they can handle only templating of
    // simple data types and not e.g. JS Objects in JSON.
    templates: {
        place: new Template(
            '<div class="item" onclick="EventManager.publish({name:\'#{eventName}\', id:\'#{id}\', distance:\'#{distance}\'})">' +
            '  <div class="image">#{displayImage}</div>' +
            '  <div class="info">' +
            '    <div class="name">#{title}</div>' +
            '    <div class="rating">#{rating}</div>' +
            '    <div class="category">#{categoryName}</div>' +
            '  </div>' +
            '  <div class="distance">#{distance}</div>' +
            '</div>'
            ),
        empty: new Template(
            '<div class="item empty">' + 
            '  <div class="name">#{label}</div>' +
            '</div>'
        )
    },

    /**
     * Override the default build to prepare the view as needed.
     */
    build: function($super, params) {
        $super(params);
	
		/* ***************************
		   PLACE OF CODE SNIPPET 11.3
		  ****************************/		

        // Remove the old data and update the snippet. Thus, old content is not shown
        // while retrieving new data, instead the default progress spinner is shown.
        this.snippets.content.data.places = undefined;
        this.snippets.content.rewrite();

        // Params allow showing one single category.
        if(params && params.categoryId && params.categoryName) {
            // If we opened this view via CategoriesView, then do not show the
            // 'Categories' shortcut on the top.
            this.snippets.categoriesLink.dom.hide();
            this.currentCategoryId = params.categoryId;
            this.currentCategoryName = params.categoryName;
        }
        else {
            // By default a shortcut to the CategoriesView is shown.
            this.snippets.categoriesLink.dom.show();
            this.currentCategoryId = undefined;
            this.currentCategoryName = undefined;
        }

        // Start retrieving the data
        this.getPlaces();
    },

    /**
     * @param {Object} evt Holds the event as it was published via the EventManager.
     *                     See the templates.place from this class.
     */
    onItemClick: function(evt) {
        util.log("{PlacesView.onItemClick} start");

        this.engine.activateView("placeView", {
            placeid: evt.id,
            distance: evt.distance
        });
    },

	// Click handlers take care of click events in the view

    onMapLinkClick: function() {
		console.log("hmm",this.snippets.content.data.places);
        this.engine.activateView("mapView",{placedata:this.snippets.content.data.places});
    },
	
    onLocationButtonClick: function() {
		console.log("Refresh location clicked");
		
		// This launches GPS location request; the functionality is
		// defined in app.js
        qype.refreshLocation();    
	},
	
    /**
     * Create the actual content HTML for the retrieved places. Is triggered only
     * if the onData templates are used, see the initialize() method.
     *
     * @return The generated HTML as a string
     */	
	constructPlacesHtml: function() {
		
		/* *******************************
		   PLACE OF CODE SNIPPET 12.4.1
		  ********************************/		
		
        var places = undefined;
        if(places = this.snippets.content.data.places) { // Check if there's proper data stored
            places = places.results;
            var t = this.templates.place; // Set the HTML template
            var arr = [];
            var lang = this.engine.getContentLang(); // Get the language set in Engine.js
            
            for(var i = 0; i < places.length; i++) { // loop through the list of places
 
				/* *******************************
				   PLACE OF CODE SNIPPET 12.4.2
				  ********************************/ 			
 
                var place = new qype.models.PlaceModel(places[i].place, lang); // initialize new PlaceModel object (see PlaceModel.js)
                var data = { // Fill template variables by using the place model
                    id: place.getId(), 
                    title: place.data.title,
                    eventName: "placeClicked",
                    categoryName: place.getCategoriesStr(),
                    distance: place.getDistanceStr(),
                    rating: '<div class="stars'+place.data.average_rating+'"></div>' + place.getReviewsStr()
                }
				var placeImage = place.getImageUrl("medium");
				if(placeImage) {
                    data.displayImage = '<div style="background-image: url(\''+placeImage+'\');" class="listItem"></div>';
                }
                arr.push(t.evaluate(data)); // Evaluate the template with given data, and add the result HTML into temporary array
            }

            if(places.length === 0) { // Special case: no places availabe
                arr.push(this.templates.empty.evaluate({
                    label: qype.str.no_data_available // Use text/HTML string defined in strings.js
                }));
            }

            return arr.join(""); // Return result array (HTML)
        }

        return "";
    },

    /**
     * Start retrieving the needed places via Qype API. Calls the API in
     * asynchronous manner.
     */
    getPlaces: function() {
        var loc = this.engine.getCurrentLocation();

        var params = {}; 
        
        if(this.currentCategoryId) {
            params.in_category = this.currentCategoryId;
        }
        
		/* *******************************
		   PLACE OF CODE SNIPPET 12.3.2
		  ********************************/		
		
        qype.API.get("positions", {
                "onSuccess": this.onGetPlaces.bind(this),
                "onFailure": this.onFailure
            },
            loc.coords.latitude + "," + loc.coords.longitude + "/places",
            params
        );
    }
	
	/* *******************************
	   PLACE OF CODE SNIPPET 12.3.1
	  ********************************/	
	,

    /**
     * Gets called if the places were successfully retrieved from the Qype API.
     *
     * @param {Ajax.Response} response Response object as coming from the Prototype.js.
     */
    onGetPlaces: function(response) {
        util.log("{PlacesView.onGetPlaces} start");
        this.snippets.content.data.places = response.responseJSON;
        
        // Handle snippet/DOM updating manually.
        util.depressurizeAll("item");
        this.snippets.header.rewrite();
        this.snippets.content.rewrite();
        util.pressurizeAll("item");
    },

    onFailure: function(response) {
        util.log("{PlacesView.onFailure}: start, response = ");
        util.log(response);
    }
});